<template>
  <div class="home">
    <div id="map">
    </div>
    <label :for="speed">
      speed:&nbsp;
      <input
        id="speed"
        type="range"
        min="10"
        max="999"
        step="10"
        v-model="speed"
      />
    </label>
    <button @click="startAnimation">{{startButton}}</button>
    <div
      ref="popup"
      class="popup"
      v-show="shopPopup"
    >
      <span
        class="icon-close"
        @click.self="closePopup"
      >✖</span>
      <div class="content">{{text}}</div>
    </div>
  </div>
</template>
<script>
import gisApi from "../../gisApi";
import "ol/ol.css";
import car from "$ui/map/sources/arrows/car.png";
import { Map, View, Feature } from "ol";
import XYZ from "ol/source/XYZ";
import { Style, Stroke, Icon, Circle as CircleStyle, Fill } from "ol/style";
import { LineString, Point } from "ol/geom";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import VectorSource from "ol/source/Vector";
import { getVectorContext } from "ol/render";
import Overlay from "ol/Overlay";
export default {
  data() {
    return {
      map: null,
      fraction: 0,
      startPoint: [12729061.664567024, 3568670.000910808],
      finalPoint: [12726932.89312517, 3566422.7522427756],
      carFeature: null,
      lineFeature: null,
      period: 5,
      aId: null,
      now: null,
      text: "起点",
      shopPopup: true,
      routeFeature: null,
      geoMarker: null,
      speed: 5,
      vectorLayer: null,
      styles: null,
      animating: false,
      startTime: "",
      startButton: "Start Animation",
      center: [12729502.20562764, 3566970.780904669],
      endMarker: null,
      coordinates: [
        [12729061.664567024, 3568670.000910808],
        [12729008.158588907, 3568551.5234950976],
        [12728958.474403888, 3568444.5116846566],
        [12728908.790510453, 3568322.212410242],
        [12728836.175275264, 3568173.160219665],
        [12728771.203626271, 3568043.2171403673],
        [12728702.410475766, 3567913.274352654],
        [12728645.082704552, 3567783.331346252],
        [12728591.576726435, 3567668.6758038243],
        [12728522.783284346, 3567550.198468299],
        [12728476.921184007, 3567416.4336688],
        [12728419.593412794, 3567286.4906623987],
        [12728163.52930972, 3566300.452968361],
        [12728045.051974194, 3566300.452968361],
        [12727869.246867456, 3566323.3841643217],
        [12727693.441702401, 3566369.2464104514],
        [12727502.349073369, 3566407.464924594],
        [12727345.653223703, 3566411.286717691],
        [12727143.095098747, 3566407.464924594],
        [12726932.89312517, 3566422.7522427756],
      ],
      startMarker: null,
      route: null,
      rotation: null,
      centerMarker: null,
      currentCoordinate: null,
      popup: null,
    };
  },
  methods: {
    //阶乘
    factorial(num) {
      if (num <= 1) {
        return 1;
      } else {
        return num * this.factorial(num - 1);
      }
    },
    //生成贝塞尔曲线
    createBezierCurvePoints(points = [], space = 0.01) {
      // 大于2个点才能有曲线
      if (points.length <= 2 || space <= 0) return points;
      let x = 0;
      let y = 0;
      // 控制点个数
      const n = points.length - 1;
      const line = [];
      for (let t = 0; t < 1; t = t + space) {
        x = 0;
        y = 0;
        for (let i = 0; i <= n; i++) {
          const [x1, y1] = points[i];
          x +=
            (this.factorial(n) / (this.factorial(i) * this.factorial(n - i))) *
            Math.pow(1 - t, n - i) *
            Math.pow(t, i) *
            x1;
          y +=
            (this.factorial(n) / (this.factorial(i) * this.factorial(n - i))) *
            Math.pow(1 - t, n - i) *
            Math.pow(t, i) *
            y1;
        }
        line.push([x, y]);
      }
      line.push(points[points.length - 1]);
      return line;
    },
    initMap() {
      this.map = new Map({
        target: document.getElementById("map"),
        layers: [
          new TileLayer({
            source: new XYZ({ url: gisApi.layerConfig.tileUrl }),
          }),
        ],
        view: new View({
          center: gisApi.mapConfig.center,
          minZoom: 15,
          maxZoom: 19,
          zoom: 15,
          projection: "EPSG:3857",
          extent: gisApi.mapConfig.extent,
        }),
      });
    },
    closePopup() {},
    addLine() {
      this.route = new LineString(
        // this.createBezierCurvePoints(this.coordinates)
        this.coordinates
      );
      this.routeFeature = new Feature({
        type: "route",
        geometry: this.route,
      });
      this.geoMarker = new Feature({
        type: "geoMarker",
        geometry: new Point(this.route.getCoordinateAt(0)),
      });
      this.startMarker = new Feature({
        type: "icon",
        geometry: new Point(this.route.getCoordinateAt(0)),
      });
      this.centerMarker = new Feature({
        type: "centerIcon",
        geometry: new Point([12728476.921184007, 3567416.4336688]),
      });
      this.endMarker = new Feature({
        type: "icon",
        geometry: new Point(this.route.getCoordinateAt(1)),
      });
      var styles = {
        route: new Style({
          stroke: new Stroke({
            width: 6,
            color: [237, 212, 0, 0.8],
          }),
        }),
        icon: new Style({
          image: new Icon({
            scale: 0.2,
            anchor: [0.5, 1],
            src: require("../assets/logo.png"),
          }),
        }),
        centerIcon: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: "black" }),
            stroke: new Stroke({
              color: "white",
              width: 2,
            }),
          }),
        }),
        geoMarker: new Style({
          image: new Icon({
            src: car,
            scale: 0.5,
            rotateWithView: true,
            rotation: this.rotation,
          }),
        }),
      };
      this.styles = styles;
      this.vectorLayer = new VectorLayer({
        source: new VectorSource({
          features: [
            this.routeFeature,
            this.geoMarker,
            this.startMarker,
            this.endMarker,
            this.centerMarker,
          ],
        }),
        style: (feature) => {
          // hide geoMarker if animation is active
          if (this.animating && feature.get("type") === "geoMarker") {
            return null;
          }
          return styles[feature.get("type")];
        },
      });
      // var newFeature = new Feature({
      //   geometry: new Point([12729061.664567024, 3568670.000910808]), //几何信息
      //   name: "标注点",
      // });
      let elPopup = this.$refs.popup; //设置弹窗
      this.popup = new Overlay({
        element: elPopup,
        positioning: "bottom-center",
        stopEvent: true,
        autoPan: true, // 如果弹窗在底图边缘时，底图会移动
        autoPanAnimation: {
          // 底图移动动画
          duration: 250,
        },
      });
      this.popup.setPosition([12729061.664567024, 3568670.000910808]);
      this.map.addLayer(this.vectorLayer);
      this.map.addOverlay(this.popup);
    },
    getRotation(prev, next) {
      const dx = prev[0] - next[0];
      const dy = prev[1] - next[1];
      return Math.atan2(dy, dx);
    },
    moveFeature(e) {
      var vectorContext = getVectorContext(e);
      var frameState = e.frameState;
      if (this.animating) {
        var elapsedTime = frameState.time - this.startTime;
        // var distance = (this.speed * elapsedTime) / 1e6;
        var index = Math.round((this.speed * elapsedTime) / 1000);
        if (index > 0 && index < this.coordinates.length - 1) {
          this.text = "在途中";
        }
        if (index == this.coordinates.length - 1) {
          this.stopAnimation(true);
          this.text = "终点";
          return;
        }
        // var currentPoint = new Point(this.route.getCoordinateAt(distance));
        // var nextPoint = new Point(
        //   this.route.getCoordinateAt(Math.min(distance + 0.001, 1))
        // );
        var currentPoint = new Point(this.coordinates[index]);
        var nextPoint = new Point(this.coordinates[index + 1]);
        var feature = new Feature(currentPoint);
        var feature1 = new Feature(nextPoint);
        var currentCoordinate = feature.getGeometry().getCoordinates();
        this.currentCoordinate = currentCoordinate;
        var nextCoordinate = feature1.getGeometry().getCoordinates();
        this.popup.setPosition(currentCoordinate);
        if (
          nextCoordinate.toString() ==
          [12728476.921184007, 3567416.4336688].toString()
        ) {
          console.log("到达中转站");
          this.centerMarker.setStyle(
            new Style({
              image: new CircleStyle({
                radius: 10,
                fill: new Fill({ color: "green" }),
                stroke: new Stroke({
                  color: "white",
                  width: 2,
                }),
              }),
            })
          );
        }
        var rotation = this.getRotation(currentCoordinate, nextCoordinate);
        vectorContext.drawFeature(
          feature,
          new Style({
            image: new Icon({
              src: car,
              scale: 0.5,
              rotateWithView: true,
              rotation: -rotation,
            }),
          })
        );
      }
      // tell OpenLayers to continue the postrender animation
      this.map.render();
    },
    startAnimation() {
      this.text = "起点";
      this.centerMarker.setStyle(
        new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: "black" }),
            stroke: new Stroke({
              color: "white",
              width: 2,
            }),
          }),
        })
      );
      if (this.animating) {
        this.stopAnimation(false);
      } else {
        this.animating = true;
        this.startTime = new Date().getTime();
        this.startButton = "Cancel Animation";
        // hide geoMarker
        this.geoMarker.changed();
        // just in case you pan somewhere else
        // this.map.getView().setCenter(this.center);
        this.vectorLayer.on("postrender", this.moveFeature);
        this.map.render();
      }
    },
    stopAnimation(ended) {
      this.animating = false;
      this.startButton = "Start Animation";
      // if animation cancelled set the marker at the beginning
      var coord = this.route.getCoordinateAt(ended ? 1 : 0);
      this.geoMarker.getGeometry().setCoordinates(coord);
      // remove listener
      this.vectorLayer.un("postrender", this.moveFeature);
    },
  },
  mounted() {
    this.initMap();
    this.addLine();
  },
};
</script>
<style lang="scss" scoped>
.home {
  height: 100%;
  width: 100%;
}
#map {
  height: 100% !important;
  width: 100%;
}
/* 弹窗样式 */
.popup {
  min-width: 280px;
  margin-bottom: 1rem;
  position: relative;
  background: #fff;
  padding: 8px 16px;
  display: flex;
  flex-direction: column;

  /* 弹窗下方的小三角形 */
  &::after {
    display: block;
    content: "";
    width: 0;
    height: 0;
    position: absolute;
    border: 12px solid transparent;
    border-top-color: #fff;
    bottom: -23px;
    left: 50%;
    transform: translateX(-50%);
  }
}
/* 关闭弹窗按钮 */
.icon-close {
  cursor: pointer;
  align-self: flex-end;
  margin-bottom: 10px;
}
</style>